import getpass
import crypt
import pam
import subprocess as sp

from PySide2.QtWidgets import *
from PySide2.QtGui import QFont

parameter_name_text = \
"""
<html><head/><body><p>
Please key in the <span style=\"font-weight:600; text-decoration: underline;\">parameter name</span>:
</p></body></html>
"""

value_type_text = \
"""
<html><head/><body><p>
And select the <span style=\"font-weight:600; text-decoration: underline;\">value type</span> for the parameter:
</p></body></html>
"""


class TypeSelectorDialog(QDialog):
    
    def __init__(self, config, parent=None):
        super(TypeSelectorDialog, self).__init__(parent=parent)
        # "config" variable should be a dict
        self.config = config
        self.init_ui()
    
    def init_ui(self):
        self.setWindowTitle("Type Selector")
        self.resize(400, 190)
        self.grid_lyt_global = QGridLayout(self)
        
        self.lbl_parameter_name = QLabel(self)
        self.lbl_parameter_name.setText(parameter_name_text)
        self.grid_lyt_global.addWidget(self.lbl_parameter_name, 0, 0, 1, 4)
        
        self.le_parameter_name = QLineEdit(self)
        self.le_parameter_name.setPlaceholderText("Case sensitive.")
        self.grid_lyt_global.addWidget(self.le_parameter_name, 1, 0, 1, 4)
        
        self.lbl_value_type = QLabel(self)
        self.lbl_value_type.setText(value_type_text)
        self.grid_lyt_global.addWidget(self.lbl_value_type, 2, 0, 1, 4)

        self.cbbox_value_type = QComboBox(self)
        self.cbbox_value_type.addItem("String")
        self.cbbox_value_type.addItem("Integer")
        self.cbbox_value_type.addItem("Floating")
        self.cbbox_value_type.addItem("Boolean")
        self.grid_lyt_global.addWidget(self.cbbox_value_type, 3, 0, 1, 4)

        self.btn_cancel = QPushButton(self)
        self.btn_cancel.setText("&Cancel")
        self.btn_cancel.setDefault(False)
        self.btn_cancel.setAutoDefault(False)
        self.btn_cancel.clicked.connect(self.slot_btn_cancel)
        self.grid_lyt_global.addWidget(self.btn_cancel, 4, 1, 1, 1)

        self.btn_ok = QPushButton(self)
        self.btn_ok.setText("&OK")
        self.btn_ok.clicked.connect(self.slot_btn_ok)
        self.grid_lyt_global.addWidget(self.btn_ok, 4, 2, 1, 1)
        
        spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.grid_lyt_global.addItem(spacer, 4, 0, 1, 1)
    
    def slot_btn_cancel(self):
        self.close()

    def slot_btn_ok(self):
        if self.le_parameter_name.text() == "":
            QMessageBox.warning(self, "Warning",
                "The \"paramenter name\" should not be empty.", QMessageBox.Ok)
            return

        if not self.le_parameter_name.text().isidentifier():
            QMessageBox.warning(self, "Warning",
                "The input \"paramenter name\" is invalid.", QMessageBox.Ok)
            return

        self.config["parameter_name"] = self.le_parameter_name.text()
        self.config["value_type"] = self.cbbox_value_type.currentText()
        self.close()


class PasswordDialog(QDialog):
    def __init__(self, parent=None, config=None):
        super(PasswordDialog, self).__init__(parent)
        self.config = config
        self.init_ui()

    def init_ui(self):
        self.resize(360, 130)
        self.setWindowTitle("Authentication Required")
        self.grid_lyt_global = QGridLayout(self)

        self.init_main_part()
        self.init_btn()

    def init_main_part(self):
        self.frm_main_part = QFrame()
        self.frm_main_part.setFrameShape(QFrame.StyledPanel)
        self.frm_main_part.setFrameShadow(QFrame.Raised)

        self.grid_lyt_main_part = QGridLayout(self.frm_main_part)
        self.vbox_lyt_main_part = QVBoxLayout()

        self.lbl_pwd = QLabel(self.frm_main_part)
        self.lbl_pwd.setText("Password for user '{}' [sudo]:".format(self.get_current_username()))
        font = QFont()
        font.setPointSize(12)
        self.lbl_pwd.setFont(font)
        self.vbox_lyt_main_part.addWidget(self.lbl_pwd)

        self.le_pwd = QLineEdit(self.frm_main_part)
        self.le_pwd.setEchoMode(QLineEdit.Password)
        self.vbox_lyt_main_part.addWidget(self.le_pwd)
        self.grid_lyt_main_part.addLayout(self.vbox_lyt_main_part, 0, 0, 1, 1)

        self.grid_lyt_global.addWidget(self.frm_main_part, 0, 0, 1, 2)

    def init_btn(self):
        self.push_btn_ok = QPushButton("OK")
        self.grid_lyt_global.addWidget(self.push_btn_ok, 1, 1, 1, 1)
        self.push_btn_ok.clicked.connect(self.slot_push_btn_ok)

        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.grid_lyt_global.addItem(spacerItem, 1, 0, 1, 1)

    def slot_push_btn_ok(self):
        if self.le_pwd.text() == "":
            QMessageBox.warning(self, "Warning",
                "The password should not be empty.", QMessageBox.Ok)
            return

        if self.validate_password(self.le_pwd.text()):
            self.config["pwd"] = self.le_pwd.text()
            self.close()

    def validate_password(self, password):
        cur_username = self.get_current_username()
        p = pam.pam()
        return p.authenticate(cur_username, password)

    @staticmethod
    def get_current_username():
        return getpass.getuser()
